using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace SvnPmtHook
{

	/// <summary>
	/// Responsible for orchestrating all of the services to gather
	/// required information and doing the actual commit to the 
	/// pmt web service.
	/// </summary>
	public class CommitProcessor
	{
		private IParse _tokenParser;
		private ISvnLogService _logService;
		private ISvnLookExecutor _svnlookExecutor;
		private string _pathToLogMessageTemplate;


		/// <summary>
		/// Initializes a new instance of the <see cref="CommitProcessor"/> class.
		/// </summary>
		/// <param name="tokenParser">The task id parser.</param>
		/// <param name="logService">The log service.</param>
		/// <param name="svnlookExecutor">The svnlook executor.</param>
		/// <param name="pathToLogMessageTemplate">The path to log message template.</param>
		public CommitProcessor(IParse tokenParser, ISvnLogService logService, ISvnLookExecutor svnlookExecutor, string pathToLogMessageTemplate)
		{
			_tokenParser = tokenParser;
			_logService = logService;
			_svnlookExecutor = svnlookExecutor;
			_pathToLogMessageTemplate = pathToLogMessageTemplate;
		}

		/// <summary>
		/// Sends commit information to PMT after someone checks something in.
		/// </summary>
		/// <param name="repo">The repository affected.</param>
		/// <param name="rev">The revision of the repo AFTER the commit.</param>
		/// <returns>A response message indicating whether the operation succeeded or failed 
		/// along with original commit info and any other details about the activity.</returns>
		public SvnLogServiceResponse Commit(string repo, int rev)
		{
			Func<string,string> exec = 
				(s) =>
				{
					return _svnlookExecutor.Execute(s, rev);
				};

			_tokenParser.LogContents = exec("log");
			CommitInfo info = new CommitInfo();
			info.Log = GetLogMessage(exec);
			info.Repository = repo;
			info.Revision = rev;
			info.UserName = exec("author").TrimEnd('\r', '\n');
			var taskIds = _tokenParser.Parse<IEnumerable<int>>("taskid");
			var tasks = new List<TaskInfo>();
            if (taskIds != null && taskIds.Count() > 0)
			{
				foreach (int taskID in taskIds)
				{
					var taskInfo = new TaskInfo();
					taskInfo.DueDate = _tokenParser.Parse<DateTime>(DateTime.MinValue, "duedate", "dd");
					taskInfo.EstimatedHours = _tokenParser.Parse<decimal>("estimatedhours", "eh");
					taskInfo.Message = _tokenParser.LogContents;
					taskInfo.TaskID = taskID;
					taskInfo.TimeSpentOnTask = _tokenParser.Parse<decimal>("hours", "timespentontask", "h");
					taskInfo.Title = _tokenParser.Parse<string>("Default title", "title", "t");
					tasks.Add(taskInfo);
				}
				
			}
			info.Tasks = tasks.ToArray();
			return _logService.LogPostCommit(info);
		}

		private string GetLogMessage(Func<string, string> exec)
		{
			var commands = new string[] { "author", "changed", "date", "diff", "info", "log" };
			if (!File.Exists(_pathToLogMessageTemplate))
				return "";

			var result = File.ReadAllText(_pathToLogMessageTemplate);
			foreach (var command in commands)
			{
				var token = "$" + command + "$";
				if (result.IndexOf(token) >= 0)
				{
					result = result.Replace(token, exec(command));
				}
			}
			return result;
		}
	}
}
